package com.popo.xml;

import java.io.IOException;
import java.io.StringBufferInputStream;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.dom4j.io.DOMReader;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class SAXTest {
	
	public static 	String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
			"<data>"+
			"<grade gredenum='gd1'>" +
			"	<class classnum='cl1'>" +
			" 		<std name='xiaohong' age='16' />" +
			"		<std name='xiaoming' age='18' >xiaoming xiaoming xiaoming xiaoming</std>" +
			"		<teacher name='tch_li' cource='chemistry'/>" +
			"		<teacher name='tch_jia' cource='physics'/>"+
			"	</class> " +
			"</grade >"+
			"<grade gredenum='gd2'>" +
			"	<class classnum='cl1'>" +
			" 		<std name='monkeysun' age='530' />" +
			"		<std name='bajiepig' age='360' />"+
			"		<std name='cleanwu' age='320' />"+
			"	</class> " +
			"	<class classnum='cl2'>" +
			"aafafafa" +
			"</class>" +
			"</grade >"+
			"</data>"
			;
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		SAXParserFactory sf = SAXParserFactory.newInstance(); 
		MyDefaultHandler df = new MyDefaultHandler();
	
		/**
		 * "<grade n='2'>" +
				"	<class n=1>" +
				" 		<std name='2l' age='22' />" +
				"		<std name='23' age='23' />"+
				"	</class> " +
				"	<class n=2>" +
				" 		<std name='2l' age='22' />" +
				"		<std name='23' age='23' />"+
				"	</class>"+
				"</grade >" +
				
		 */
        try {
			SAXParser sp = sf.newSAXParser();
			StringBufferInputStream in = new StringBufferInputStream(xml);
			sp.parse(in, df);
			System.out.println();
			Data data = df.root;
			System.out.println(data);
		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SAXException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
        
	}
	
	

}

/**
 * 设计的数据对象结构
 * @author liboliu
 *
 */
class Data{
	//Node的名字
	public String name=null;
	//包含的数据 此数据应该与son互斥
	public String data=null;
	//属性
	public HashMap<String, String> attr= null;
	//子数据
	public HashMap<String,ArrayList<Data>> son=null;
	
	 //对象翻译为XML
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		
		StringBuilder sb = new StringBuilder();
		//node名字
		sb.append("<"+name+" ");
		//属性
		if(attr!=null){
			Set<String> keys = attr.keySet();
			Iterator<String> it = keys.iterator();
			while(it.hasNext()){
				 String key_ = it.next();
				 sb.append(" "+key_+"="+ attr.get(key_)+" ");
				 
			 }
		}
		
		sb.append(" >\n");
		
		//包含的数据或子项
		if(son!=null){
			Set<String> keys =son.keySet();
			 Iterator<String> it = keys.iterator();
			 while(it.hasNext()){
				 String key_ = it.next();
				 ArrayList<Data> sonData = son.get(key_);
				 for(Data d :sonData){
					 sb.append(d);
				 }
				 
			 }
		}
		
		if(data!=null){
			sb.append(data+"\n");
		}
		//结束
		sb.append("</"+name+">\n");
		return sb.toString();
	}
	
}


class MyDefaultHandler extends DefaultHandler{
	
	
	
	LinkedList<Data> stack =null;

	Data parent = null;
	Data self =null;
	Data root =null;
	
	int step=0;
	LinkedList<Object> lo = new LinkedList<Object>();
	boolean newDowcument = true;
	public MyDefaultHandler() {
		super();
		// TODO Auto-generated constructor stub
	}

	@Override
	public void endDocument() throws SAXException {
		// TODO Auto-generated method stub
		//释放
		stack=null;
		parent=null;
		self=null;
		super.endDocument();
		
	}
	
	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		//解析完后自己出栈
		stack.removeFirst();
		self = stack.getFirst();
		System.out.println("remove "+qName);
		// TODO Auto-generated method stub
		super.endElement(uri, localName, qName);
		
	}
	
	@Override
	public void startDocument() throws SAXException {
		// TODO Auto-generated method stub
		//初始化 root linklist
		root = new Data();
		//初始话栈
		stack= new LinkedList<Data>();
		//把root进栈
		stack.addFirst(root);
		super.startDocument();
	
	
	}
	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {	
		//创建自己
		self = new Data();
		self.name=qName;
		//获取父对象这里应该 出栈后 在入栈 但是用 linkedList  直接获取栈顶数据  就不用 进行出入栈操作了
		parent = stack.peekFirst();
		//自己进栈
		stack.addFirst(self);
		System.out.println("new self"+qName);
		//把自己添加到parent里面去
		addSelfInParent(self,parent,qName);
		//填充属性
//		System.out.println("uri="+uri+",localName:"+localName+",qName:"+qName);
		int attributesl =attributes.getLength();
		if(attributesl>0){
			self.attr = new HashMap<String, String>();
		}
		for(int i=0;i<attributesl;i++){
			
			self.attr.put(attributes.getLocalName(i), attributes.getValue(i));
		}
		super.startElement(uri, localName, qName, attributes);
	}
	
	/**
	 * 
	 * @param self
	 * @param parent
	 * @param key
	 */
	@SuppressWarnings("unchecked")
	private void addSelfInParent(Data self,
			Data parent,String key) {
		// TODO Auto-generated method stub
		
		if(parent.son==null){
			parent.son= new HashMap<String, ArrayList<Data>>();
			ArrayList<Data> d = new ArrayList<Data>();
			parent.son.put(key, d);
			d.add(self);
		}else{
			if(parent.son.containsKey(key)){
				parent.son.get(key).add(self);
			}else{
				ArrayList<Data> d = new ArrayList<Data>();
				parent.son.put(key, d);
				d.add(self);
			}
		}
	}
	
	@Override
	public void characters(char[] arg0, int arg1, int arg2) throws SAXException {
		// TODO Auto-generated method stub
		self.data=new String(arg0,arg1,arg2);
		System.out.println(self.data);
		super.characters(arg0, arg1, arg2);
	}
	
}
